import win32gui
import win32ui
import win32con
import numpy as np
import cv2
import time
import ctypes
import win32api
import win32con
import keyboard
import threading

# 第二套模板
TEMPLATE2_PATH = './template_pic/template2.png'
TPL2 = cv2.imread(TEMPLATE2_PATH, cv2.IMREAD_COLOR)
if TPL2 is None:
    raise FileNotFoundError(f'找不到模板文件 {TEMPLATE2_PATH}')
TPL2_H, TPL2_W = TPL2.shape[:2]

def locate_template2(frame, threshold=0.80):
    res = cv2.matchTemplate(frame, TPL2, cv2.TM_CCOEFF_NORMED)
    _, max_val, _, max_loc = cv2.minMaxLoc(res)
    return max_loc if max_val >= threshold else None

# 固定点击位置（客户区坐标）
FIX_CLICK_X = 870       # 自己改成实际坐标
FIX_CLICK_Y = 500

# 全局开关
running = False          # True=运行中  False=暂停
lock = threading.Lock()

def toggle_running():
    global running
    with lock:
        running = not running

# 在后台线程注册 F1 热键
keyboard.add_hotkey('f1', toggle_running)


def client_click(hwnd, x, y):
    """
    在窗口客户区 (x,y) 处单击一次
    """
    # 把客户区坐标转成屏幕坐标
    screen_x, screen_y = win32gui.ClientToScreen(hwnd, (x, y))
    win32api.SetCursorPos((screen_x, screen_y))
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0)
    win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, 0, 0, 0, 0)


# 全局只加载一次模板
TEMPLATE_PATH = './template_pic/template.png'
TPL = cv2.imread(TEMPLATE_PATH, cv2.IMREAD_COLOR)
if TPL is None:
    raise FileNotFoundError(f'找不到模板文件 {TEMPLATE_PATH}')

TPL_H, TPL_W = TPL.shape[:2]

def locate_template(frame, threshold=0.80):
    """
    返回匹配到的左上角 (x, y)；未找到返回 None
    """
    res = cv2.matchTemplate(frame, TPL, cv2.TM_CCOEFF_NORMED)
    _, max_val, _, max_loc = cv2.minMaxLoc(res)
    if max_val >= threshold:
        return max_loc
    return None

# 让进程 DPI Aware，避免在高分辨率屏截到缩小图
ctypes.windll.shcore.SetProcessDpiAwareness(2)

# ---------- 1. 找到目标窗口 ----------
def find_window(title_substring: str):
    def enum_cb(hwnd, extra):
        if title_substring.lower() in win32gui.GetWindowText(hwnd).lower():
            extra.append(hwnd)

    hwnd_list = []
    win32gui.EnumWindows(enum_cb, hwnd_list)
    if not hwnd_list:
        raise RuntimeError(f'找不到包含 "{title_substring}" 的窗口')
    return hwnd_list[0]

# ---------- 2. 截取窗口客户区 ----------
def capture_window(hwnd):
    """返回 BGR numpy 数组；失败返回 None"""
    if win32gui.IsIconic(hwnd):
        win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
        time.sleep(0.1)

    left, top, right, bottom = win32gui.GetClientRect(hwnd)
    w, h = right - left, bottom - top
    if w <= 0 or h <= 0:
        return None

    x0, y0 = win32gui.ClientToScreen(hwnd, (left, top))

    hwnd_dc = win32gui.GetWindowDC(hwnd)
    mfc_dc  = win32ui.CreateDCFromHandle(hwnd_dc)
    save_dc = mfc_dc.CreateCompatibleDC()
    bmp = win32ui.CreateBitmap()
    bmp.CreateCompatibleBitmap(mfc_dc, w, h)
    save_dc.SelectObject(bmp)
    save_dc.BitBlt((0, 0), (w, h), mfc_dc, (0, 0), win32con.SRCCOPY)

    buf = bmp.GetBitmapBits(True)
    img = np.frombuffer(buf, dtype='uint8')
    img.shape = (h, w, 4)
    img = img[:, :, :3]          # BGRA -> BGR

    win32gui.DeleteObject(bmp.GetHandle())
    save_dc.DeleteDC()
    mfc_dc.DeleteDC()
    win32gui.ReleaseDC(hwnd, hwnd_dc)

    return img

# ---------- 3. 主循环 ----------
def main():
    target_title = "神仙道"
    hwnd = find_window(target_title)
    print(f'已锁定窗口: {win32gui.GetWindowText(hwnd)}')

    fps = 4
    delay = int(1000 / fps)
    last_click_time = time.time()

    while True:
        with lock:           # 防止热键读写冲突
            if not running:
                time.sleep(0.1)
                continue

        frame = capture_window(hwnd)
        if frame is None:
            time.sleep(0.02)
            continue
        frame = frame.copy()
        pt = locate_template(frame)
        pt2 = locate_template2(frame)
        if pt2 is not None:
            # 画红框标记固定位置
            cv2.rectangle(frame,
                          (FIX_CLICK_X-10, FIX_CLICK_Y-10),
                          (FIX_CLICK_X+10, FIX_CLICK_Y+10),
                          (0, 0, 255), 2)
            cv2.putText(frame, "FixedClick", (FIX_CLICK_X-30, FIX_CLICK_Y-15),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)

            # 点击固定位置（同样加冷却）
            now = time.time()
            if now - last_click_time > 0.5:
                client_click(hwnd, FIX_CLICK_X, FIX_CLICK_Y)
                last_click_time = now
        if pt is not None:
            # 画绿色矩形
            cv2.rectangle(frame, pt, (pt[0]+TPL_W, pt[1]+TPL_H), (0, 255, 0), 2)
            cv2.putText(frame, f'Matched! ({pt[0]},{pt[1]})',
                        (pt[0], pt[1]-5), cv2.FONT_HERSHEY_SIMPLEX,
                        0.5, (0, 255, 0), 1)
                # 计算“左下方 50 像素”的位置
            click_x = pt[0] -50                # 模板左上角 x
            click_y = pt[1] + TPL_H    # 模板底边再往下 50 像素

            # 执行点击
            client_click(hwnd, click_x, click_y)
                # ---------- 检测并点击第二模板 ----------

        cv2.imshow("App Capture", frame)
        if cv2.waitKey(delay) & 0xFF == ord('q'):
            break
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()
